﻿#ifndef _COMPTR_INC_
#define _COMPTR_INC_

template <class T>
class _TXNoAddRefReleaseOnCComPtr : public T
{
	public:
		virtual int addref()=0;
		virtual int release()=0;
};

//TXCComPtrBase provides the basis for all other smart pointers
//The other smartpointers add their own constructors and operators
template <class T>
class TXCComPtrBase
{
protected:
	TXCComPtrBase() 
	{
		p = NULL;
	}
//	TXCComPtrBase( int nNull)
//	{
//		(void)nNull;
//		p = NULL;
//	}
	TXCComPtrBase( T* lp)
	{
		p = lp;
		if (p != NULL)
			p->addref();
	}
public:
	typedef T _PtrClass;
	~TXCComPtrBase() 
	{
		if (p)
			p->release();
	}
	operator T*()
	{
		return p;
	}
	T& operator*() const
	{
		ATLENSURE(p!=NULL);
		return *p;
	}
	//The assert on operator& usually indicates a bug.  If this is really
	//what is needed, however, take the address of the p member explicitly.
	T** operator&() 
	{
		//ATLASSERT(p==NULL);
		if( p != NULL )
		{
#ifdef __i386
		__asm__("int $3\n");
#endif
		}
		return &p;
	}
	_TXNoAddRefReleaseOnCComPtr<T>* operator->() const 
	{
		//ATLASSERT(p!=NULL);
		return (_TXNoAddRefReleaseOnCComPtr<T>*)p;
	}
	bool operator!() const 
	{
		return (p == NULL);
	}
	bool operator<( T* pT) const 
	{
		return p < pT;
	}
	bool operator!=( T* pT) const
	{
		return !operator==(pT);
	}
	bool operator==( T* pT) const 
	{
		return p == pT;
	}

	// Release the interface and set to NULL
	void release() 
	{
		T* pTemp = p;
		if (pTemp)
		{
			p = NULL;
			pTemp->release();
		}
	}

	T* p;
};

template <class T>
class TXCComPtr : public TXCComPtrBase<T>
{
public:
	TXCComPtr() 
	{
	}
//	TXCComPtr(int nNull)  :
//	TXTXCComPtrBase<T>(nNull)
//	{
//	}
	TXCComPtr(T* lp)  :
	TXCComPtrBase<T>(lp)

	{
	}
	TXCComPtr( const TXCComPtr<T>& lp)  :
	TXCComPtrBase<T>(lp.p)
	{
	}
	
	T* operator=( T* lp) 
	{
		if(*this!=lp)
		{
			if (lp != NULL)
				lp->addref();
			if (this->p)
				this->p->release();
			this->p = lp;
			return static_cast<T*>(this->p);
		}
		return *this;
	}

	T* operator=( TXCComPtr<T>& lp) 
	{
		if(*this!=lp)
		{
			if (lp != NULL)
				lp->addref();
			if (this->p)
				this->p->release();
			this->p = lp;

			return static_cast<T*>(this->p);
		}

		return *this;
	}
};

////////////////////////////////////////////////////////////
// Class to Adapt CComBSTR and TXCComPtr for use with STL containers
// the syntax to use it is
// std::vector< TXCAdapt <CComBSTR> > vect;

template <class T>
class TXCAdapt
{
public:
	TXCAdapt()
	{
	}
	TXCAdapt(const T& rSrc) :
	m_T( rSrc )
	{
	}
	
	TXCAdapt(const TXCAdapt& rSrCA) :
	m_T( rSrCA.m_T )
	{
	}
	
	TXCAdapt& operator=(const T& rSrc)
	{
		m_T = rSrc;
		return *this;
	}
	bool operator<(const T& rSrc) const
	{
		return m_T < rSrc;
	}
	bool operator==(const T& rSrc) const
	{
		return m_T == rSrc;
	}
	bool operator!=( T* rSrc) const
	{
		return !operator==(rSrc);
	}
	operator T&()
	{
		return m_T;
	}
	
	operator const T&() const
	{
		return m_T;
	}

	T m_T;
};

#endif /*_COMPTR_INC_*/
